package com.fyfeng.fcanvas;

import java.util.Iterator;
import java.util.Stack;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

public class FCanvas extends View {

	private static final String tag = FCanvas.class.getSimpleName();

	private Bitmap mBitmap;// 所有的canvas对这个bitmap操作.
	private Paint mPaint = new Paint(Paint.DITHER_FLAG);// 图片画刷//对bitmap图像操作的paint;

	private Canvas mCanvas;// 画图工具

	private PaintPath mPencil;// 畫筆
	private PaintPath mErase;// 橡皮擦

	private int mState = FMode.READ; // 默认为阅读模式

	private float mX, mY;
	private static final float TOUCH_TOLERANCE = 4;

	private Stack<PaintPath> mStack = new Stack<PaintPath>();

	
	private int mWidth;
	private int mHeight;
	/**
	 * 路徑保存
	 * 
	 * @author yuzw
	 * 
	 */
	class PaintPath {
		public Paint paint;
		public Path path;

		public PaintPath(Paint paint, Path path) {
			this.paint = paint;
			this.path = path;
		}
	}

	public FCanvas(Context context, int width, int height) {
		super(context);
		this.mWidth = width;
		this.mHeight = height;
		
		this.initView();
	}

	public FCanvas(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public FCanvas(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public FCanvas(Context context) {
		super(context);
	}

	private void initView() {

		if (null != this.mBitmap) {
			return;
		}

		Bitmap bitmap = FFileUtils.getNoteBitmap(FFileUtils.mNoteFile);

		if (null == bitmap) {
			bitmap = this.createTransparentBitmap();// 如果原來沒有塗鴉則創建一個新的畫布.
			Log.d(tag, "原來沒有塗畫.");
		}

		
		this.init(bitmap);
	}

	private Bitmap createTransparentBitmap() {
		return Bitmap.createBitmap(this.mWidth, this.mHeight, Bitmap.Config.ARGB_8888);
	}

	/**
	 * 初始化画笔
	 */
	private void newPencil() {
		
		Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setDither(true);
		paint.setColor(Color.GREEN);
		paint.setStyle(Paint.Style.STROKE);
		paint.setStrokeJoin(Paint.Join.ROUND);
		paint.setStrokeCap(Paint.Cap.ROUND);
		paint.setStrokeWidth(2);

		Path path = new Path();

		mPencil = new PaintPath(paint, path);
	}

	/**
	 * 初始化橡皮擦
	 */
	private void newEraser() {

		Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setDither(true);
		paint.setColor(Color.TRANSPARENT);
		paint.setStyle(Paint.Style.STROKE);
		paint.setStrokeJoin(Paint.Join.ROUND);
		paint.setStrokeCap(Paint.Cap.ROUND);
		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
		paint.setAlpha(0);
		paint.setStrokeWidth(35);

		Path path = new Path();

		mErase = new PaintPath(paint, path);
		
	}

	private void init(Bitmap bitmap) {

		this.newPencil();
		this.newEraser();

		mBitmap = bitmap;
		mCanvas = new Canvas(bitmap);
		
		this.invalidate();
	}

	public void clear() {

		Bitmap bitmap = this.createTransparentBitmap();
		this.init(bitmap);
	}

	public Bitmap getBitmap() {
		return this.mBitmap;
	}

	public void toErase() {
		this.mState = FMode.ERASE;

		Log.d(tag, "切换到擦除状态.");
		Toast.makeText(this.getContext(), "切换到擦除状态.", Toast.LENGTH_SHORT).show();
	}

	public void toPaint() {
		this.mState = FMode.PAINT;

		Log.d(tag, "切换到涂写状态.");
		Toast.makeText(this.getContext(), "切换到涂写状态.", Toast.LENGTH_SHORT).show();
	}

	public void toRead() {
		this.mState = FMode.READ;

		Log.d(tag, "切换到阅读状态.");
		Toast.makeText(this.getContext(), "切换到阅读状态.", Toast.LENGTH_SHORT).show();
	}

	public int getState() {
		return this.mState;
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
	}

	@Override
	protected void onDraw(Canvas canvas) {

		super.onDraw(canvas);

		if (null == mBitmap || null == mPaint) {
			return;
		}

		canvas.drawBitmap(mBitmap, 0, 0, mPaint);// 画上次的背景图片。

		if (FMode.PAINT == mState) {// 如果是绘图
			canvas.drawPath(mPencil.path, mPencil.paint);
		}

	}

	private void touch_start(float x, float y) {

		Path path = null;
		if (FMode.PAINT == mState) {
			this.newPencil();
			path = mPencil.path;

		} else if (FMode.ERASE == mState) {
			this.newEraser();
			path = mErase.path;

		}

		// path.reset();

		path.moveTo(x, y);
		mX = x;
		mY = y;
	}

	private void touch_move(float x, float y) {

		Path path = null;
		Paint paint = null;

		if (FMode.PAINT == mState) {
			path = mPencil.path;
			paint = mPencil.paint;
		} else if (FMode.ERASE == mState) {
			path = mErase.path;
			paint = mErase.paint;
		}

		float dx = Math.abs(x - mX);
		float dy = Math.abs(y - mY);
		
		if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
			path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
			mX = x;
			mY = y;
		}

		mCanvas.drawPath(path, paint);

	}

	private void touch_up() {

		Path path = null;
		Paint paint = null;

		if (FMode.PAINT == mState) {
			path = mPencil.path;
			paint = mPencil.paint;
		} else if (FMode.ERASE == mState) {
			path = mErase.path;
			paint = mErase.paint;
		}

		path.lineTo(mX, mY);
		// commit the path to our offscreen
		mCanvas.drawPath(path, paint);
		// kill this so we don't double draw

		// path.reset();

		if (FMode.PAINT == mState) {
			this.mStack.push(mPencil);
			Log.d(tag, "向堆棧添加Pair");
		}

	}
	
	public void undo(){
		int size = this.mStack.size();
		Log.d(tag, "堆栈 - size="+size);
		
		if(this.mStack.isEmpty()){
			Log.i(tag, "堆棧信息爲空."); return;
		}
		
		this.mStack.pop();
		
		Log.d(tag, "去除顶部最后一次图画.");
		
		Bitmap notebitmap = FFileUtils.getNoteBitmap(FFileUtils.mNoteFile);//读取上次的保存的图画
		
		Bitmap bitmap = this.createTransparentBitmap();
		
		this.init(bitmap);//创建一个新的画布
		if(null != notebitmap){
		mCanvas.drawBitmap(notebitmap, 0, 0, mPaint);//把上次保存的图写画出来，
		}
		//把刚才绘画的图写给画上去。
		Iterator<PaintPath> it = this.mStack.iterator();
		
		while(it.hasNext()){
			PaintPath pp =it.next();
			mCanvas.drawPath(pp.path, pp.paint);
		}
		
		this.invalidate();

	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		float x = event.getX();
		float y = event.getY();

		if (FMode.READ == mState) {
			return false;
		}

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			touch_start(x, y);
			invalidate();
			break;
		case MotionEvent.ACTION_MOVE:
			touch_move(x, y);
			invalidate();
			break;
		case MotionEvent.ACTION_UP:
			touch_up();
			invalidate();
			break;
		}
		return true;
	}

}
